import { EventDispatcher } from "../../base/event/EventDispatcher";
import { IRecoverable } from "../../base/pool/IRecoverable";
import { Pool } from "../../base/pool/Pool";
import { Task } from "../task/Task";
import { TaskSequence } from "../task/TaskSequence";
import { IView } from "./IView";

export type ViewConfig = {
    /**
     * 视图路径
     */
    path:string,
    /**
     * 视图名称
     */
    name?:string,
    /**
     * 视图默认显示层级
     */
    zIndex?:number,
    /**
     * 视图加载器类型
     */
    loaderType?:string,
    /**
     * 是否缓存视图
     */
    cache?:boolean,
}

/**
 * 视图加载器
 */
export abstract class IViewLoader extends EventDispatcher implements IRecoverable  {
    protected _pool:Pool<IViewLoader>;
    protected _asset:any;
    protected _initializer:TaskSequence = new TaskSequence();
    constructor(pool:Pool<IViewLoader>){ 
        super()
        this._pool = pool;
    }

    public abstract init(config:ViewConfig):IViewLoader;

    public load(task?:Task):void {
        if(this._asset){ 
            task && task.onComplete();
            return 
        }
        if(task){
            this._initializer.once(Task.Event.ERROR, this, (type, a, error:{code, msg})=>{
                task.onError(error.code, error.msg);
            });
            this._initializer.on(Task.Event.PROGRESS, this, (type, a, percent:number)=>{
                task.onProgress(percent);
            });
        }
        
        this._initializer.once(Task.Event.COMPLETE, this, ()=>{
            this._initializer.reset();
            task && task.onComplete();
        });
        this._initializer.start();
    }

    /**
     * 创建视图
     * @param viewName 视图名称
     * @param recoverLoader 还原loader
     */
    public abstract initView<T extends IView>(viewName:string, recoverLoader?:boolean): T;
    
    public destroy():void{
        this.offAll();
        this._initializer.reset();
        this._initializer = null;
        this._asset = null;
        this._pool = null;
    }

    reset(): void {
        this._initializer.reset();
        this.offAll();
        this._asset = null;
    }

    recover():void{
        this._pool.recover(this);
    }
}
